package com.bst.md.service.impl;

import com.bst.common.annotation.DataSource;
import com.bst.common.base.api.BaseDWService;
import com.bst.common.config.RedisTemplateConfig;
import com.bst.common.constant.JobConstant;
import com.bst.common.vo.DimDataVO;
import com.bst.common.vo.JobDimVO;
import com.bst.base.domain.BaseMsg;
import com.bst.md.domain.MdMedPubfld;
import com.bst.md.domain.MdMedTbFld;
import com.bst.md.mapper.MdMedDimDataMapper;
import com.bst.base.service.IBaseMsgService;
import com.bst.md.service.IMdMedPubfldService;
import com.bst.md.service.IMdMedDimService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * mdMedDim服务实现类
 * Created by hozeData on 2021/07/05.
 */
@Service("dimService")
public class MdMedDimServiceImpl implements IMdMedDimService {

    @Autowired
    RedisTemplateConfig redisTemplate;
    @Autowired
    private IMdMedPubfldService mdMedPubfldService;
    @Autowired
    private IBaseMsgService baseMsgService;
    @Autowired
    private MdMedDimDataMapper mdMedDimDataMapper;
    @Autowired
    BaseDWService baseDWService;

    @Override
    @DataSource(value = JobConstant.DB_CLS_DW)
    public Map<String, JobDimVO> findAllDimData(List<MdMedPubfld> pubfldList) {
        Map<String,JobDimVO> dimDataVOMap = new HashMap<>();
        String sdDimtp;Map<String,String> data;JobDimVO dimDataVO;
        for(MdMedPubfld fld:pubfldList) {
            sdDimtp = fld.getSdDimtp();
            if(StringUtils.isNotBlank(sdDimtp)) {
                dimDataVO = new JobDimVO();
                if("3".equals(sdDimtp)) { // 自动填充维度
                    data = this.findDimCdAndNa(fld.getCdTbDim());
                    if(data==null) data = new HashMap<>();
                    dimDataVO.setData(data);
                }
                dimDataVO.setSdDimtp(sdDimtp);
                dimDataVO.setDimTable(fld.getCdTbDim());
                dimDataVOMap.put(fld.getIdPubfld(),dimDataVO);
            }
        }
        return dimDataVOMap;
    }
    Lock lock = new ReentrantLock();
    /**
     * 1）判断公共字段是否为校验维度，且表存在
     * 2）判断值是否存在
     * 3）不存在插入
     * @param dataMap
     * @return
     */
    @Override
    @DataSource(value = JobConstant.DB_CLS_DW)
    public List<BaseMsg> dimDataCheck(Map<String, Map<String,Object>> gDataMap,Map<String, JobDimVO> jobDimVOMap) {
        Set<String> redisData;
        String dimTbName,idPubfld;
        Map<String,Object> value;
        List<DimDataVO> dimDataList;
        Map<String,List<DimDataVO>> dimDataVOMap = new HashMap<>();
        Map<String, Map<String,Object>> dataMap = new ConcurrentHashMap<>();
        dataMap.putAll(gDataMap);
        try{
            lock.lock();
            for(Map.Entry<String, Map<String,Object>> entry:dataMap.entrySet()) {
                idPubfld = entry.getKey();
                dimTbName = jobDimVOMap.get(idPubfld).getDimTable();
                value = entry.getValue();
                if(StringUtils.isBlank(dimTbName)) {
                    continue;
                }
                redisData = redisTemplate.getSet(JobConstant.REDIS_PREF_DIMDATA+dimTbName.toUpperCase());
                if(redisData.size()==0) {
                    dimDataList = this.queryDimData(dimTbName);
                    if(dimDataList.size()>0) {
                        redisData = new HashSet();
                        for(DimDataVO dimDataVO:dimDataList) {
                            redisData.add(dimDataVO.getCd());
                        }
                        redisTemplate.putSet(redisData.toArray(),JobConstant.REDIS_PREF_DIMDATA+dimTbName.toUpperCase());
                    }
                }
                dimDataList = this.findInsertData(redisData,value);
                if(dimDataList.size()>0) {
                    dimDataVOMap.put(dimTbName,dimDataList);
                }
            }
            List<BaseMsg> list = null;
            if(dimDataVOMap.size()>0) {
                list = this.insertDimDatas(dimDataVOMap);
                for(Map.Entry<String,List<DimDataVO>> entry:dimDataVOMap.entrySet()) {
                    redisData = new HashSet();
                    for(DimDataVO vo:entry.getValue()) {
                        redisData.add(vo.getCd());
                    }
                    if(redisData.size()>0) {
                        redisTemplate.putSet(redisData.toArray(),JobConstant.REDIS_PREF_DIMDATA+entry.getKey().toUpperCase());
                    }
                }
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return null;
    }

    @Override
    @DataSource(value = JobConstant.DB_CLS_DW)
    public Map<String, String> findDimCdAndNa(String tb) {
        List<DimDataVO> dimData = this.queryDimData(tb);

        if (dimData == null || dimData.size() == 0) return new HashMap<>();

        Map<String, String> dim = new HashMap<>();
        for (DimDataVO dimDatum : dimData) {
            dim.put(dimDatum.getCd(), dimDatum.getNa());
        }

        return dim;
    }

    @Override
    @DataSource(value = JobConstant.DB_CLS_DW)
    public List<Map<String, Object>> findDimDataByTbname(List<MdMedTbFld> fldList, String tableName) {
        if(fldList==null) return null;
        String[] names=new String[fldList.size()];
        int i=0;
        String sql = "select ";
        for(MdMedTbFld tbFld:fldList) {
            names[i++] = tbFld.getNaPubfld();
            if(i==fldList.size()) {
                sql += tbFld.getIdPubfld()+" from "+tableName;
            } else {
                sql += tbFld.getIdPubfld()+", ";
            }

        }
        List<Map<String,Object>> data = baseDWService.findBySql(sql);
        return data;
    }

    @Override
    @DataSource(value = JobConstant.DB_CLS_DW)
    public List<Map<String, Object>> findDimDataByTbname(List<MdMedTbFld> fldList, String tableName,String na) {
        if(fldList==null) return null;
        String[] names=new String[fldList.size()];
        int i=0;
        String sql = "select top 100 ";
        for(MdMedTbFld tbFld:fldList) {
            names[i++] = tbFld.getNaPubfld();
            if(i==fldList.size()) {
                sql += tbFld.getIdPubfld()+" from "+tableName;
            } else {
                sql += tbFld.getIdPubfld()+", ";
            }
        }
        if(StringUtils.isNotEmpty(na)) {
            sql += " where cd like '%"+na+"%' or na like '%"+na+"%'";
        }
        List<Map<String,Object>> data = baseDWService.findBySql(sql);
        return data;
    }

    @Override
    @DataSource(value = JobConstant.DB_CLS_DW)
    public int remove(String tableName, String cd) {
        return mdMedDimDataMapper.deleteByCd(tableName,cd);
    }

    @Override
    @DataSource(value = JobConstant.DB_CLS_DW)
    public List<DimDataVO> queryDimData(String dimTbName) {
        List<DimDataVO> dimDataList = mdMedDimDataMapper.queryDimData(dimTbName);
        return dimDataList;
    }

    @Override
    @DataSource(value = JobConstant.DB_CLS_DW)
    public List<DimDataVO> queryDimDataWithOrder(String tb) {
        List<DimDataVO> dimDataList = mdMedDimDataMapper.queryDimDataWithOrder(tb);
        return dimDataList;
    }

    @Override
    @DataSource(value = JobConstant.DB_CLS_DW)
    public List<BaseMsg> insertDimDatas(Map<String,List<DimDataVO>> dimDataVOMap) {
        Map<String,String> dimData;List<DimDataVO> dataVOList;
        BaseMsg baseMsg;
        List<BaseMsg> baseMsgList = new ArrayList<>();
        for(Map.Entry<String,List<DimDataVO>> entry:dimDataVOMap.entrySet()) {
            dimData = this.findDimCdAndNa(entry.getKey());
            dataVOList = new ArrayList<>();
            for(DimDataVO vo:entry.getValue()) {
                if(dimData.get(vo.getCd())!=null) {
                    continue;
                }
                baseMsg = new BaseMsg(JobConstant.MSG_CODE_D01,"维度表["+entry.getKey()+"]新增["+vo.getCd()+","+vo.getNa()+"]记录");
                baseMsgList.add(baseMsg);
                dataVOList.add(vo);
                try {
                    mdMedDimDataMapper.insert(vo, entry.getKey());
                } catch (Exception e) {
                    baseMsgList.add(new BaseMsg(JobConstant.MSG_CODE_D02,"维度表["+entry.getKey()+"]新增["+vo.getCd()+","+vo.getNa()+"]失败，请核实原因",e.getMessage()));
                }
            }
        }
        return baseMsgList;
    }

    @Override
    @DataSource(value = JobConstant.DB_CLS_DW)
    public List<Map<String, Object>> queryDayData(String mm) {
        return mdMedDimDataMapper.queryDayData(mm);
    }

    @Override
    @DataSource(value = JobConstant.DB_CLS_DW)
    public List<Map<String, Object>> queryHisDeptData() {
        return mdMedDimDataMapper.queryHisDeptData();
    }


    private List<DimDataVO> findInsertData(Set redisData, Map<String,Object> valueMap) {
        List<DimDataVO> dataVOList = new ArrayList<>();
        DimDataVO dataVO;
        String key;Object value;
        for(Map.Entry<String,Object> entry:valueMap.entrySet()) {
            key = entry.getKey();
            value = entry.getValue();
            if(!redisData.contains(key)) {
                dataVO = new DimDataVO();
                dataVO.setCd(key);
                dataVO.setNa(value.toString());
                dataVO.setDtSysCre(new Date());
                dataVO.setEuTp("0"); //自动插入
                dataVOList.add(dataVO);
            }
        }
        return dataVOList;
    }





}
